{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TABLE 4 (Main Text)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded: jcr_mutiny_conflict_data.dta  |  Rows=1,599,624  Cols=130\n",
      "After lag-drop for lag models: 1,559,628 rows\n",
      "\\begin{table}\n",
      "\\caption{}\n",
      "\\label{}\n",
      "\\begin{center}\n",
      "\\begin{tabular}{lllllll}\n",
      "\\hline\n",
      "                         & m7        & m8        & m9        & m10       & m11       & m12        \\\\\n",
      "\\hline\n",
      "Violent mutiny               & 0.927***  &           &           &           &           &            \\\\\n",
      "                         & (0.124)   &           &           &           &           &            \\\\\n",
      "Violent mutiny\\_lag1         &           &           &           & 0.452***  &           &            \\\\\n",
      "                         &           &           &           & (0.160)   &           &            \\\\\n",
      "Military size (binary)               &           & 0.801***  &           &           &           &            \\\\\n",
      "                         &           & (0.149)   &           &           &           &            \\\\\n",
      "Military size (binary)\\_lag1         &           &           &           &           & 0.512***  &            \\\\\n",
      "                         &           &           &           &           & (0.174)   &            \\\\\n",
      "Mutiny duration (cat.)       &           &           & 0.349***  &           &           &            \\\\\n",
      "                         &           &           & (0.051)   &           &           &            \\\\\n",
      "Mutiny duration (cat.)\\_lag1 &           &           &           &           &           & 0.170***   \\\\\n",
      "                         &           &           &           &           &           & (0.060)    \\\\\n",
      "Military spending per soldier (logged)       & -0.129*** & \n",
      "...\n",
      "\n",
      "LaTeX table (m7–m12) written to: C:\\Users\\rmuhi\\OneDrive\\Desktop\\Mutiny_Conflict Paper_All\\Replication File\\logit_results_table_7_12.tex\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# ----------------------------------------------------------\n",
    "# 0) Lightweight installer if packages are missing\n",
    "# ----------------------------------------------------------\n",
    "\n",
    "try:\n",
    "    import pandas as _pd; import statsmodels as _sm; import matplotlib as _mpl\n",
    "except Exception:\n",
    "    import sys, subprocess\n",
    "    subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-U\", \"pandas\", \"statsmodels\", \"matplotlib\"])\n",
    "\n",
    "from pathlib import Path\n",
    "import pandas as pd\n",
    "import statsmodels.formula.api as smf\n",
    "from statsmodels.iolib.summary2 import summary_col\n",
    "\n",
    "# ----------------------------\n",
    "# 1) Load data\n",
    "# ----------------------------\n",
    "file_path = Path(r\"C:\\Users\\rmuhi\\OneDrive\\Desktop\\Mutiny_Conflict Paper_All\\Replication File\\jcr_mutiny_conflict_data.dta\")\n",
    "if not file_path.exists():\n",
    "    raise FileNotFoundError(f\"Could not find .dta file at: {file_path}\")\n",
    "\n",
    "data = pd.read_stata(file_path)\n",
    "print(f\"Loaded: {file_path.name}  |  Rows={len(data):,}  Cols={len(data.columns)}\")\n",
    "\n",
    "# ----------------------------\n",
    "# 2) Create lags \n",
    "# ----------------------------\n",
    "data = data.sort_values(['id','year'])\n",
    "\n",
    "data['mutiny_t_lag1'] = data.groupby('id')['mutiny_t'].shift(1)\n",
    "data['violent_t_lag1'] = data.groupby('id')['violent_t'].shift(1)\n",
    "data['size_t_b_lag1'] = data.groupby('id')['size_t_b'].shift(1)\n",
    "data['mduration_t_cat3_lag1'] = data.groupby('id')['mduration_t_cat3'].shift(1)\n",
    "\n",
    "# A stricter sample for lagged RHS models to avoid missingness\n",
    "data_lagged = data.dropna(subset=['violent_t_lag1','size_t_b_lag1','mduration_t_cat3_lag1'])\n",
    "print(f\"After lag-drop for lag models: {len(data_lagged):,} rows\")\n",
    "\n",
    "# ----------------------------\n",
    "# 3) Model formulas \n",
    "# ----------------------------\n",
    "formula7  = 'dispute2 ~ violent_t + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula8  = 'dispute2 ~ size_t_b + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula9  = 'dispute2 ~ mduration_t_cat3 + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula10 = 'dispute2 ~ violent_t_lag1 + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula11 = 'dispute2 ~ size_t_b_lag1 + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula12 = 'dispute2 ~ mduration_t_cat3_lag1 + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "\n",
    "# ----------------------------\n",
    "# 4) Fit helper (HC1-robust, with fallback)\n",
    "# ----------------------------\n",
    "def fit_logit_robust(formula, df):\n",
    "    model = smf.logit(formula, df)\n",
    "    try:\n",
    "        res = model.fit(disp=False, cov_type='HC1')\n",
    "    except TypeError:\n",
    "        res0 = model.fit(disp=False)\n",
    "        res = res0.get_robustcov_results(cov_type='HC1')\n",
    "    return res\n",
    "\n",
    "# ----------------------------\n",
    "# 5) Fit models\n",
    "# ----------------------------\n",
    "\n",
    "result7  = fit_logit_robust(formula7,  data)\n",
    "result8  = fit_logit_robust(formula8,  data)\n",
    "result9  = fit_logit_robust(formula9,  data)\n",
    "\n",
    "# lagged RHS use 'data_lagged' to avoid missingness\n",
    "result10 = fit_logit_robust(formula10, data_lagged)\n",
    "result11 = fit_logit_robust(formula11, data_lagged)\n",
    "result12 = fit_logit_robust(formula12, data_lagged)\n",
    "\n",
    "# ----------------------------\n",
    "# 6) Table builder for LaTeX\n",
    "# ----------------------------\n",
    "def build_latex_table(results, model_names, add_checks=True):\n",
    "    # Show key regressors (time polynomials intentionally omitted)\n",
    "    regressor_order = [\n",
    "        # possible key regressors from earlier batch and current batch\n",
    "        'mutiny_t', 'mutiny_t_lag1',\n",
    "        'violent_t', 'violent_t_lag1',\n",
    "        'size_t_b', 'size_t_b_lag1',\n",
    "        'mduration_t_cat3', 'mduration_t_cat3_lag1',\n",
    "        # controls\n",
    "        'lmmilex_persol_t', 'years_since_coup', 'ucdp_civconf_t2',\n",
    "        'defense_target', 'capprop', 'jdem', 'majorpower', 'cold_war',\n",
    "        'Intercept'  # may show as 'const'; we relabel below\n",
    "    ]\n",
    "\n",
    "    info_dict = {\n",
    "        'N':         lambda x: f\"{int(x.nobs):d}\",\n",
    "        'Pseudo R²': lambda x: f\"{getattr(x, 'prsquared', float('nan')):.3f}\",\n",
    "    }\n",
    "\n",
    "    table = summary_col(\n",
    "        results=results,\n",
    "        float_format='%0.3f',\n",
    "        stars=True,\n",
    "        model_names=model_names,\n",
    "        info_dict=info_dict,\n",
    "        regressor_order=regressor_order,\n",
    "        drop_omitted=True\n",
    "    )\n",
    "\n",
    "    latex_lines = table.as_latex().splitlines()\n",
    "\n",
    "    # Insert checkmark rows after \"Pseudo R²\"\n",
    "    if add_checks:\n",
    "        insert_idx = next((i for i, ln in enumerate(latex_lines) if 'Pseudo R²' in ln), None)\n",
    "        if insert_idx is not None:\n",
    "            checks = ' & ' + ' & '.join(['\\\\checkmark'] * len(results)) + r' \\\\'\n",
    "            extra_rows = [r\"Time polynomials\" + checks, r\"Robust SE\" + checks]\n",
    "            for offset, new_line in enumerate(extra_rows, start=1):\n",
    "                latex_lines.insert(insert_idx + offset, new_line)\n",
    "\n",
    "    # Friendly labels (escaped + unescaped)\n",
    "    replacements = {\n",
    "        # newly added vars\n",
    "        'violent_t':                   'Violent mutiny',\n",
    "        'violent\\\\_t':                 'Violent mutiny',\n",
    "        'violent_t_lag1':              'Violent mutiny (t-1)',\n",
    "        'violent\\\\_t\\\\_lag1':          'Violent mutiny (t-1)',\n",
    "\n",
    "        'size_t_b':                    'Military size (binary)',\n",
    "        'size\\\\_t\\\\_b':                'Military size (binary)',\n",
    "        'size_t_b_lag1':               'Military size (binary, t-1)',\n",
    "        'size\\\\_t\\\\_b\\\\_lag1':         'Military size (binary, t-1)',\n",
    "\n",
    "        'mduration_t_cat3':            'Mutiny duration (cat.)',\n",
    "        'mduration\\\\_t\\\\_cat3':        'Mutiny duration (cat.)',\n",
    "        'mduration_t_cat3_lag1':       'Mutiny duration (cat., t-1)',\n",
    "        'mduration\\\\_t\\\\_cat3\\\\_lag1': 'Mutiny duration (cat., t-1)',\n",
    "\n",
    "        # earlier key ones\n",
    "        'mutiny_t':                    'Military mutiny',\n",
    "        'mutiny\\\\_t':                  'Military mutiny',\n",
    "        'mutiny_t_lag1':               'Military mutiny (t-1)',\n",
    "        'mutiny\\\\_t\\\\_lag1':           'Military mutiny (t-1)',\n",
    "\n",
    "        # controls\n",
    "        'lmmilex_persol_t':            'Military spending per soldier (logged)',\n",
    "        'lmmilex\\\\_persol\\\\_t':        'Military spending per soldier (logged)',\n",
    "        'years_since_coup':            'Years since last coup',\n",
    "        'years\\\\_since\\\\_coup':        'Years since last coup',\n",
    "        'ucdp_civconf_t2':             'Civil conflict',\n",
    "        'ucdp\\\\_civconf\\\\_t2':         'Civil conflict',\n",
    "        'defense_target':              'Defense alliance',\n",
    "        'defense\\\\_target':            'Defense alliance',\n",
    "        'capprop':                     'Capability ratio',\n",
    "        'jdem':                        'Both democracy',\n",
    "        'majorpower':                  'Major power',\n",
    "        'cold_war':                    'Cold War',\n",
    "        'cold\\\\_war':                  'Cold War',\n",
    "\n",
    "        'Intercept':                   'Constant',\n",
    "        'const':                       'Constant'\n",
    "    }\n",
    "\n",
    "    fixed_lines = []\n",
    "    for line in latex_lines:\n",
    "        for old, new in replacements.items():\n",
    "            if old in line:\n",
    "                line = line.replace(old, new)\n",
    "        fixed_lines.append(line)\n",
    "\n",
    "    return \"\\n\".join(fixed_lines)\n",
    "\n",
    "# ----------------------------\n",
    "# 7) Build & save LaTeX table\n",
    "# ----------------------------\n",
    "latex_7_12 = build_latex_table(\n",
    "    [result7, result8, result9, result10, result11, result12],\n",
    "    ['m7','m8','m9','m10','m11','m12']\n",
    ")\n",
    "\n",
    "# Preview and save\n",
    "print(latex_7_12[:1500] + \"\\n...\\n\")\n",
    "out_tex = file_path.parent / \"table_4.tex\"\n",
    "out_tex.write_text(latex_7_12, encoding=\"utf-8\")\n",
    "print(f\"LaTeX table (m7–m12) written to: {out_tex}\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
